# buildin

from django.shortcuts import render, HttpResponse
from django.views.generic import ListView, DetailView
from django.db.models import Q

from blog.models import Article, Category, Comment
from blog.froms import CommentForm
# Create your views here.


# def index(request):
#     return render(request, "index.html")

class Index(ListView):
    model = Article
    template_name = "index.html"
    queryset = Article.objects.all().order_by("-id")
    # 分页
    # 设置分页时文章的数量
    paginate_by = 3


class CategoryList(ListView):
    model = Article
    template_name = "category.html"
    paginate_by = 3

    # 定义通过分类查询QuerySet
    def get_queryset(self):
        # 按参数传入的分类id进行查询并按照文章的编号降序排序
        return Article.objects.filter(category=self.kwargs["category"]).order_by("-id")

    # 增加额外要传递给模板的数据
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # 通过分类id查询分类对象
        category = Category.objects.get(id=self.kwargs["category"])
        # 将分类对象名称传递给模板的数据中
        context["category"] = category.name
        return context

# 评论
# 1.遍历所有的评论数据，如果是文章的评论（顶级评论）存入一个列表
# 2.如果不是文章的评论(也就是回复他人评论的评论)，以评论目标(父级评论)的id为键存入字典
# 3.循环遍历所有的顶级评论，并通过递归函数归纳每一组评论内容(一个顶级评论和与之相关的回复评论)
class ArticleDetail(DetailView):
    model = Article
    template_name = "detail.html"

    # 重写get_object 返回实例对象
    # def get_object(self, queryset=None):
    #     return Article.objects.get(id=self.kwargs["detai"])

    def comment_sort(self, comments):  # 评论排序函数
        self.comment_list = []   # 排序后的评论列表
        self.top_level = []      # 存储顶级评论
        self.sub_level = {}      # 存储回复评论

        # 遍历所有的评论
        for comment in comments:
            # 如果没有回复目标，存入顶级评论列表
            if comment.reply == None:
                self.top_level.append(comment)
            else:
                # 如果有回复目标，以回复目标(父级评论)id为键存入字典
                self.sub_level.setdefault(comment.reply.id, []).append(comment)

        for top_comment in self.top_level:
            self.format_show(top_comment)
        return self.comment_list

    # 递归函数
    def format_show(self, top_comment):
        # 将参数评论存入列表
        self.comment_list.append(top_comment)
        try:
            # 获取单数评论的所有回复评论
            self.kids = self.sub_level[top_comment.id]
        except KeyError:
            # 如果不存在回复评论，结束递归
            pass
        else:
            for kid in self.kids:
                self.format_show(kid)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # 通过文章id查询评论内容
        comments = Comment.objects.filter(article=self.kwargs["pk"])
        # 将排序归类后的文章列表存入并传递到模板的数据中
        context["comments"] = self.comment_sort(comments)

        # 创建评论表单对象
        comment_form = CommentForm()
        # 将表单对象传递到模板的数据中
        context["comment_form"] = comment_form
        return context


def publish_comment(request):
    """
    发布评论函数
    :param request:
    :return:
    """
    if request.method == "POST":
        # 创建评论对象
        comment = Comment()
        # 获得评论所属文章
        article_id = request.POST.get("article")
        article = Article.objects.get(id=article_id)

        if request.POST.get("reply") != '0':
            # 如果回复的不是文章而是他人的评论， 那么需要设置回复的目标评论
            comment.reply = Comment.objects.get(id=request.POST.get("reply"))
        comment.article = article
        # 将用户的输入和评论对象结合为完整的表单数据对象
        form = CommentForm(request.POST, instance=comment)
        # 如果这个表单数据验证有效
        if form.is_valid():
            # 将表单数据存入数据库
            try:
                form.save()
                result = "200"  # 提交数据成功
            except:
                result = "10000"  # 提交结果为失败的编码
        else:
            # 如果表单数据验证无效
            result = "10000"   # 提交失败编码
        return HttpResponse(result)
    else:
        # 如果不是post请求
        return HttpResponse("非法请求")


class Search(ListView):
    model = Article
    template_name = "search.html"
    paginate_by = 3

    def get_queryset(self):
        # 获取查询关键字
        key = self.request.GET.get("key", None)
        if not key:
            key = self.request.session["key"]

        if key:
            self.request.session["key"] = key
            return Article.objects.filter(Q(title__icontains=key) | Q(content__icontains=key)).order_by("-id")
        else:
            return None

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # context["key"] = self.request.GET.get("key", None)
        context["key"] = self.request.session["key"]
        return context
